home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / CBGRX103.ZIP / contrib / libgrx / src / p4bitblt.c < prev    next >
Text File  |  1993-12-06  |  8KB  |  292 lines

  1. /** 
  2.  ** P4BITBLT.C 
  3.  **
  4.  **  Copyright (C) 1992, Csaba Biegl
  5.  **    820 Stirrup Dr, Nashville, TN, 37221
  6.  **    csaba@vuse.vanderbilt.edu
  7.  **
  8.  **  This file is distributed under the terms listed in the document
  9.  **  "copying.cb", available from the author at the address above.
  10.  **  A copy of "copying.cb" should accompany this file; if not, a copy
  11.  **  should be available from where this file was obtained.  This file
  12.  **  may not be distributed without a verbatim copy of "copying.cb".
  13.  **  You should also have received a copy of the GNU General Public
  14.  **  License along with this program (it is in the file "copying");
  15.  **  if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  16.  **  Cambridge, MA 02139, USA.
  17.  **
  18.  **  This program is distributed in the hope that it will be useful,
  19.  **  but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  **  GNU General Public License for more details.
  22.  **/
  23.  
  24. #include "p4.h"
  25. #include "memcopy.h"
  26. #include "bitcopy.h"
  27. #include "gmalloc.h"
  28.  
  29. #define  SHIFT        8        /* need to shift pixels */
  30. #define  EDGEONLY   4        /* copy masked edge only (when no shift) */
  31. #define  REVERSE    4        /* do reverse shift */
  32.  
  33. #define  SFT_INIT   0x100    /* more bits in 1st byte of dst than in src */
  34. #define  SFT_NOLAST 0x200    /* do not read last byte when shifting */
  35.  
  36. void _GrP4PixCopy(GC *dst,long da,GC *src,long sa,int width,int height,int op)
  37. {
  38.     pixptr dp1,ddp,sp1,ssp,temp;
  39.     long dpoff = dst->gc_planeoffset;
  40.     long spoff = src->gc_planeoffset;
  41.     int  doff  = dst->gc_lineoffset;
  42.     int  soff  = src->gc_lineoffset;
  43.     char vdst  = dst->gc_onscreen;
  44.     char vsrc  = src->gc_onscreen;
  45.     char usetemp  = FALSE;
  46.     char reverse  = FALSE;
  47.     char edgeonly = FALSE;
  48.     char readdst  = FALSE;
  49.     int  plane,maskwdt;
  50.     int  shift,shftwdt;
  51.     int  cmode,linewdt;
  52.     int  doff2,soff2;
  53.     int  mask;
  54.  
  55.     if((width <= 0) || (height <= 0)) return;
  56.     cmode = op = C_OPER(op);
  57.     mask  = 0;
  58.     maskwdt = 0;
  59.     shftwdt = 0;
  60.     if((src->gc_baseaddr != dst->gc_baseaddr) || (da < sa)) {
  61.         if((shift = P_OFFSET((int)da + width)) != 0) {
  62.         width -= shift;
  63.         R_MASK(mask) = (unsigned char)(0xff00 >> shift);
  64.         maskwdt++;
  65.         }
  66.         if((shift = P_OFFSET(da)) != 0) {
  67.         width -= (8 - shift);
  68.         L_MASK(mask) = (unsigned char)(0xff >> shift);
  69.         maskwdt++;
  70.         }
  71.         if((width >>= 3) < 0) {
  72.         L_MASK(mask) &= R_MASK(mask);
  73.         R_MASK(mask) = 0;
  74.         maskwdt--;
  75.         width = 0;
  76.         }
  77.         if((shift -= P_OFFSET(sa)) != 0) {
  78.         cmode |= SHIFT;
  79.         if(shift < 0) { shift += (8 + SFT_INIT); shftwdt++; }
  80.         if((P_XPOS(sa) + width + maskwdt + shftwdt) > soff) {
  81.             if(R_MASK(mask) != 0) {
  82.             shift |= SFT_NOLAST;
  83.             shftwdt--;
  84.             }
  85.             else if(width > 0) {
  86.             R_MASK(mask) = 0xff;
  87.             shift |= SFT_NOLAST;
  88.             shftwdt--;
  89.             maskwdt++;
  90.             width--;
  91.             }
  92.             else if(shftwdt > 0) {
  93.             shftwdt = 0;
  94.             shift = 8 + SFT_INIT - shift;
  95.             cmode |= REVERSE;
  96.             }
  97.             else return;
  98.         }
  99.         }
  100.         ddp = P_ADDRESS(dst,da);
  101.         ssp = P_ADDRESS(src,sa);
  102.         _ClrDir();
  103.     }
  104.     else {
  105.         linewdt = width - 1;
  106.         if((shift = P_OFFSET((int)da + width)) != 0) {
  107.         width -= shift;
  108.         L_MASK(mask) = (unsigned char)(0xff00 >> shift);
  109.         maskwdt++;
  110.         }
  111.         if((shift = P_OFFSET(da)) != 0) {
  112.         width -= (8 - shift);
  113.         R_MASK(mask) = (unsigned char)(0xff >> shift);
  114.         maskwdt++;
  115.         }
  116.         if((width >>= 3) < 0) {
  117.         L_MASK(mask) &= R_MASK(mask);
  118.         R_MASK(mask) = 0;
  119.         maskwdt--;
  120.         width = 0;
  121.         }
  122.         sa += linewdt;
  123.         da += linewdt;
  124.         if((shift = P_OFFSET(sa) - P_OFFSET(da)) != 0) {
  125.         if(shift < 0) { shift += (8 + SFT_INIT); shftwdt++; }
  126.         cmode |= (SHIFT | REVERSE);
  127.         if((width + maskwdt + shftwdt) > (P_XPOS(sa) + 1)) {
  128.             if(R_MASK(mask) != 0) {
  129.             shift |= SFT_NOLAST;
  130.             shftwdt--;
  131.             }
  132.             else if(width > 0) {
  133.             R_MASK(mask) = 0xff;
  134.             shift |= SFT_NOLAST;
  135.             shftwdt--;
  136.             maskwdt++;
  137.             width--;
  138.             }
  139.             else if(shftwdt > 0) {
  140.             shftwdt = 0;
  141.             shift = 8 + SFT_INIT - shift;
  142.             cmode &= ~REVERSE;
  143.             }
  144.             else return;
  145.         }
  146.         }
  147.         ddp = (pixptr)dst->gc_baseaddr +
  148.         ((COORD_Y(da) + height - 1) * doff) +
  149.         P_XPOS(da);
  150.         ssp = (pixptr)src->gc_baseaddr +
  151.         ((COORD_Y(sa) + height - 1) * soff) +
  152.         P_XPOS(sa);
  153.         soff = (-soff);
  154.         doff = (-doff);
  155.         reverse = TRUE;
  156.         _SetDir();
  157.     }
  158.     if(vdst) {
  159.         _SetVGASetResetPlanes(0);
  160.         _SetVGAWriteMask(0xff);
  161.         _SetVGAColorFunction(VGA_FUNC_SET);
  162.         if(maskwdt || (op != C_SET)) readdst = TRUE;
  163.         if(vsrc) {
  164.         if(!shift && width && (op == C_SET) && _GrCanBcopyInBlit) {
  165.             _SetVGAWriteMode(1);
  166.             linewdt = L_MASK(mask) ? (reverse ? -1 : 1) : 0;
  167.             dp1 = ddp + linewdt + _GrWrOnlyOffset;
  168.             sp1 = ssp + linewdt + _GrRdOnlyOffset;
  169.             linewdt = reverse ? (-width) : width;
  170.             doff2 = doff - linewdt;
  171.             soff2 = soff - linewdt;
  172.             _SaveDS();
  173.             _BlkCpyB(FAST,dp1,doff2,sp1,soff2,width,height);
  174.             _RestoreDS();
  175.             _SetVGAWriteMode(0);
  176.             if(!maskwdt) goto done;
  177.             edgeonly = TRUE;
  178.         }
  179.         if(_GrBigFrameBuffer) {
  180.             if(_GrCanBcopyInBlit && !readdst) {
  181.             ssp += _GrRdOnlyOffset;
  182.             ddp += _GrWrOnlyOffset;
  183.             }
  184.             else {
  185.             linewdt = width + maskwdt + shftwdt;
  186.             temp = (pixptr)_GrGetTempBuffer(linewdt << 2);
  187.             if(temp == (pixptr)NULL) goto done;
  188.             spoff = (long)linewdt;
  189.             if(reverse) temp += (linewdt - 1);
  190.             usetemp = TRUE;
  191.             vsrc = readdst;
  192.             }
  193.         }
  194.         }
  195.         vsrc |= readdst;
  196.     }
  197.     if((shift == 0) && ((width == 0) || edgeonly)) {
  198.         linewdt = width + maskwdt - 1;
  199.         if(reverse) {
  200.         linewdt = (-linewdt);
  201.         width    = (-width);
  202.         }
  203.         edgeonly = TRUE;
  204.         cmode |= EDGEONLY;
  205.     }
  206.     _SaveDS();
  207.     while(--height >= 0) {
  208.         dp1 = ddp;
  209.         sp1 = ssp;
  210.         if(usetemp) {
  211.         sp1 = temp;
  212.         for(plane = 0; plane < 4; plane++) {
  213.             _SetVGAReadPlane(plane);
  214.             if(!edgeonly)
  215.             _RowCpyB(TEMPBUFFER,sp1,ssp,linewdt);
  216.             else {
  217.             sp1[0]         = ssp[0];
  218.             sp1[linewdt] = ssp[linewdt];
  219.             }
  220.             sp1 += (int)spoff;
  221.         }
  222.         sp1 = temp;
  223.         }
  224.         for(plane = 0; plane < 4; plane++) {
  225.         if(vdst) _SetVGAWritePlane(plane);
  226.         if(vsrc) _SetVGAReadPlane(plane);
  227.         switch(cmode) {
  228.           case C_SET:
  229.             _CopyMskLine(dp1,sp1,mask,width);
  230.             break;
  231.           case C_XOR:
  232.             _CopyMskLineXor(dp1,sp1,mask,width);
  233.             break;
  234.           case C_OR:
  235.             _CopyMskLineOr(dp1,sp1,mask,width);
  236.             break;
  237.           case C_AND:
  238.             _CopyMskLineAnd(dp1,sp1,mask,width);
  239.             break;
  240.           case (C_SET | EDGEONLY):
  241.             _CopyMskEdge(dp1,sp1,mask,width);
  242.             break;
  243.           case (C_XOR | EDGEONLY):
  244.             _CopyMskEdgeXor(dp1,sp1,mask,width);
  245.             break;
  246.           case (C_OR | EDGEONLY):
  247.             _CopyMskEdgeOr(dp1,sp1,mask,width);
  248.             break;
  249.           case (C_AND | EDGEONLY):
  250.             _CopyMskEdgeAnd(dp1,sp1,mask,width);
  251.             break;
  252.           case (C_SET | SHIFT):
  253.             _FwdShiftLine(dp1,sp1,shift,mask,width);
  254.             break;
  255.           case (C_XOR | SHIFT):
  256.             _FwdShiftLineXor(dp1,sp1,shift,mask,width);
  257.             break;
  258.           case (C_OR | SHIFT):
  259.             _FwdShiftLineOr(dp1,sp1,shift,mask,width);
  260.             break;
  261.           case (C_AND | SHIFT):
  262.             _FwdShiftLineAnd(dp1,sp1,shift,mask,width);
  263.             break;
  264.           case (C_SET | SHIFT | REVERSE):
  265.             _RevShiftLine(dp1,sp1,shift,mask,width);
  266.             break;
  267.           case (C_XOR | SHIFT | REVERSE):
  268.             _RevShiftLineXor(dp1,sp1,shift,mask,width);
  269.             break;
  270.           case (C_OR | SHIFT | REVERSE):
  271.             _RevShiftLineOr(dp1,sp1,shift,mask,width);
  272.             break;
  273.           case (C_AND | SHIFT | REVERSE):
  274.             _RevShiftLineAnd(dp1,sp1,shift,mask,width);
  275.             break;
  276.         }
  277.         *((long *)&dp1) += dpoff;
  278.         *((long *)&sp1) += spoff;
  279.         }
  280.         ddp += doff;
  281.         ssp += soff;
  282.     }
  283.     _RestoreDS();
  284.       done:
  285.     _ClrDir();
  286.     if(vdst) {
  287.         _SetVGASetResetPlanes(0x0f);
  288.         _SetVGAWriteAllPlanes();
  289.     }
  290. }
  291.  
  292.